#pragma once

#include "nef_import.h"
#include <boost/preprocessor.hpp>
#include "resolve_type.h"

namespace nef {

template<typename Base>
struct nef_base 
{ 
	typedef Base base_t;
};

template<typename T>
struct nef_base_resolver
{
	static_assert(sizeof(T) == 0, "The specified T must be a nef_base");

	static void Resolve_imports(Catalog &cat, T &val)
	{

	}
	static void Resolve_exports(Catalog &cat, T &val)
	{

	}
};

template<typename Base>
struct nef_base_resolver<nef_base<Base>>
{
	static void Resolve_imports(Catalog &cat, Base &val)
	{
		resolve_imports(cat, val);
	}
	static void Resolve_exports(Catalog &cat, Base &val)
	{
		resolve_exports(cat, val);
	}
};

}

BOOST_PP_REPEAT(MAX_BASES, PP_TYPE_TEST, base)

#define PP_DECLARE_BASE_RESOLVE(z, n, _) \
	namespace nef {\
	template<typename Trait, typename T, bool val> \
struct resolve_base_type_ ## n ## _t \
{ \
	template<typename CT> static void Resolve_import(CT &c, const T &val) { } \
	template<typename CT> static void Resolve_export(CT &c, const T &val) { } \
}; \
	\
	template<typename Trait, typename T> \
struct resolve_base_type_ ## n ## _t<Trait, T, true> \
{ \
	template<typename CT> \
	static void Resolve_import(CT &c, T &val) \
{ \
	typedef typename Trait::base ## n::base_t base_t; \
	static_assert(is_type<base_t, T>::value, "The type T must inherit from base"); \
	nef_base_resolver<typename Trait::base ## n>::Resolve_imports(c, val); \
} \
	\
	template<typename CT> \
	static void Resolve_export(CT &c, T &val) \
{ \
	typedef typename Trait::base ## n::base_t base_t; \
	static_assert(is_type<base_t, T>::value, "The type T must inherit from base"); \
	nef_base_resolver<typename Trait::base ## n>::Resolve_exports(c, val); \
} \
}; \
	\
	template<typename Trait, typename T = Trait> \
struct resolve_base_type_ ## n \
	: resolve_base_type_ ## n ## _t<Trait, T, has_base ## n ## _test<Trait>::value> \
{}; }

BOOST_PP_REPEAT(MAX_BASES, PP_DECLARE_BASE_RESOLVE, _)

#define PP_RESOLVE_BASE_T(z, C, rtype) resolve_base_type_ ## C<nef_traits<T>, T>::Resolve_ ## rtype(cat, val);
